import win32serviceutil
import win32service
import win32event
import winerror
import sqlite3
import servicemanager
import configparser
import time
# import tkinter
# import tkinter.messagebox
import sys
import os
import urllib.parse
import urllib.request
import json

class WinPollManager(win32serviceutil.ServiceFramework):
    """
    #1.安装服务
    python WinPollManager.py install
 
    #2.让服务自动启动
    python WinPollManager.py --startup auto install
 
    #3.启动服务
    python WinPollManager.py start
 
    #4.重启服务
    python WinPollManager.py restart
 
    #5.停止服务
    python WinPollManager.py stop
 
    #6.删除/卸载服务
    python WinPollManager.py remove
    """
 
    _svc_name_ = "py_patrol_service_manager"  # 服务名
    _svc_display_name_ = "py_patrol_service_manager"  # 服务在windows系统中显示的名称
    _svc_description_ = "python windows monitor agent by jsti"  # 服务的描述
 
    def __init__(self, args):
        win32serviceutil.ServiceFramework.__init__(self, args)
        self.hWaitStop = win32event.CreateEvent(None, 0, 0, None)
        self.isAlive = True
        self._poll_intvl = 30
        self.process_result = ''
        self.send_data = ''
 
    def SvcDoRun(self):
        while self.isAlive:
            try:
                self.handler()
            except Exception  as e:
                self.log(e)
            
            # self.popWindow()
            time.sleep(self._poll_intvl)
 
    def SvcStop(self):
        self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
        win32event.SetEvent(self.hWaitStop)
        self.isAlive = False

    def handler(self):
        ## log
        self.log('checking new data')
        ## read config info
        myconfig = self.getMyconfig()
        patroldb_config = configparser.ConfigParser()
        patroldb_config.read(myconfig)
        resultdir = patroldb_config.get('default','resultdir')
        dbname = patroldb_config.get('default','dbname')
        dbdir = patroldb_config.get('default','dbdir') 
        serverurl = patroldb_config.get('default','serverurl')
        station = patroldb_config.get('default','station')
        stored_file_modified_time = patroldb_config.get('default','filetime')   
        syncid = patroldb_config.get('default','syncid')    

        ## judge patroldb is latest
        file_modified_time = self.getFileModifiedTime(dbdir+dbname)
        if stored_file_modified_time == file_modified_time :
            return

        ## fetch patroldb -> origin data
        conn = sqlite3.connect(dbdir+dbname)
        cursor = conn.cursor()
        cursor.execute('select OriginID,CardID,MeterID,Time from origin where OriginID > ? order by OriginID desc',(syncid,))
        values = cursor.fetchall()
        reduced_data = {}
        for item in values:
            originid = item[0]
            cardid = item[1]
            meterid = item[2]
            if originid > int(syncid):
                syncid = str(originid)
            key = '%s-%s' % (cardid,meterid)
            reduced_data[key] = item
            # if key in reduced_data:
            #     pass
            # else:
            #     reduced_data[key] = item
        ## close conn
        cursor.close()
        conn.close()

        ## filter data
        result_data = []
        for key in reduced_data:
            item = reduced_data[key]
            dd = {}
            dd['cardid'] = item[1]
            dd['meterid'] = item[2]
            dd['time'] = str(item[3])
            dd['sendstation'] = station
            result_data.append(dd)

        ## send data to server
        self.process_result = self.sendData(serverurl,result_data)
        prjson = json.loads(self.process_result)
        if prjson['result_code'] != 0 :
            return

        ## update patroldbConfig
        patroldb_config.set('default','filetime',file_modified_time)
        patroldb_config.set('default','syncid',syncid)
        with open(myconfig,'w+') as ff:
            patroldb_config.write(ff)
        
        ## write data to file
        f = open(resultdir + 'result.txt','a')
        timestr = time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())
        f.write('data:\n%ssystime:%s \n' % (json.dumps(result_data),timestr))
        f.close()
        
        ## log
        self.log(json.dumps(result_data))

    
    '''获取文件的修改时间'''
    def getFileModifiedTime(self,filepath):
        file_modified_time = time.localtime(os.path.getmtime(filepath))
        return time.strftime('%Y-%m-%d %H:%M:%S',file_modified_time)

    def getMyconfig(self):
        ## todo 需要依次检测 C,D,E盘符下patrolService.conf文件是否存在
        config_path = ''
        disks = ['C','D','E','F']
        for disk in disks:
            if os.path.exists(disk+':/patrolService.conf'):
                config_path = disk+':/patrolService.conf'
                break
        conf = configparser.ConfigParser()
        conf.read(config_path)
        myconfig = conf.get('default','myconfig')
        return myconfig

    def log(self,content):
        myconfig = self.getMyconfig()
        patroldb_config = configparser.ConfigParser()
        patroldb_config.read(myconfig)
        resultdir = patroldb_config.get('default','resultdir')
        f = open(resultdir+'log.txt','a')
        timestr = time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())
        f.write('-------------\nsystime:%s\n%s\n' % (timestr,content,))
        f.close()

    def sendData(self,url,content):
        # url = 'http://localhost:8089/app/index/syncPatrolDeviceData'
        params = {
            'data':content
        }
        data = bytes(urllib.parse.urlencode(params), encoding='utf8')
        response = urllib.request.urlopen(url, data=data)
        return response.read().decode('utf-8')


if __name__ == '__main__':
    if len(sys.argv) == 1:
        try:
            evtsrc_dll = os.path.abspath(servicemanager.__file__)
            servicemanager.PrepareToHostSingle(WinPollManager)
            servicemanager.Initialize('WinPollManager', evtsrc_dll)
            servicemanager.StartServiceCtrlDispatcher()
        except win32service.error as details:
            if details[0] == winerror.ERROR_FAILED_SERVICE_CONTROLLER_CONNECT:
                win32serviceutil.usage()
    else:
        win32serviceutil.HandleCommandLine(WinPollManager)  # 括号里参数可以改成其他名字，但是必须与class类名一致；